package com.ruoyi.produce.base.mrp.service;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.produce.base.bom.domain.Bom;
import com.ruoyi.produce.base.bom.mapper.BomMapper;
import com.ruoyi.produce.base.bom.service.IBomService;
import com.ruoyi.produce.base.mrp.domain.MRP;
import com.ruoyi.produce.process.planself.domain.ProducePlanSelfCond;
import com.ruoyi.produce.process.planself.domain.ProducePlanSelfDomain;
import com.ruoyi.produce.process.planself.domain.ProducePlanSelfDto;
import com.ruoyi.produce.process.planself.service.IProducePlanSelfService;
import com.ruoyi.psi.base.product.mapper.ProductMapper;
import com.ruoyi.psi.base.warehouse.domain.WarehouseCond;
import com.ruoyi.psi.base.warehouse.service.IWarehouseService;
import com.ruoyi.psi.purchase.apply.domain.PurchaseApply;
import com.ruoyi.psi.purchase.apply.domain.PurchaseApplyList;
import com.ruoyi.psi.purchase.apply.service.IPurchaseApplyService;
import com.ruoyi.psi.sale.order.domain.SaleOrderCond;

import com.ruoyi.psi.sale.order.domain.SaleOrderListDto;
import com.ruoyi.psi.sale.order.service.ISaleOrderService;
import com.ruoyi.utils.ID.IdUtil;
import com.ruoyi.utils.UtilsAdd;
import com.ruoyi.utils.UtilsList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * MRP运算
 * 业务层执行
 * @author Drj 2021/6/28
 */
@Service
public class MRPServiceImpl implements IMRPService {

    @Autowired
    private IProducePlanSelfService producePlanSelfService;
    @Autowired
    private IBomService bomService;
    @Autowired
    private BomMapper bomMapper;
    @Autowired
    private ISaleOrderService saleOrderService;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private IPurchaseApplyService purchaseApplyService;
    @Autowired
    private IdUtil idUtil;
    @Autowired
    private IWarehouseService warehouseService;

    /**
     * 通过MRP获取生产计划
     *
     * @return
     */
    @Override
    public List<ProducePlanSelfDto> selectProducePlanSelf(ProducePlanSelfCond cond) {
        List<ProducePlanSelfDto> temp = producePlanSelfService.selectProducePlanSelfListByFinished(cond);
        int i = 0;
        for ( ;  i < temp.size(); ) {
            //1.如果产品没有对应的结构清单则不在选择范围内
            if (StringUtils.isNull(bomService.selectBom(temp.get(i).getProduceId()))){
                temp.remove(i);
            }else {
                i++;
            }
        }
        return temp;
    }

    /**
     * 生产产品通过MRP生成产品毛需求
     *
     * @param producePlanSelf
     * @return
     */
    @Override
    public Bom selectDemandListByProducePlanSelf(ProducePlanSelfDto producePlanSelf) {
        if (StringUtils.isNull(bomService.selectBom(producePlanSelf.getProduceId()))){
            return null;
        }
        Bom temp = bomService.selectBom(producePlanSelf.getProduceId());//子件也包含在内
        temp.setNumberRequire(producePlanSelf.getPlanSelfNumber());//成品数量
        temp.setProduceChild(selectDemandChildList(temp));//计算子件所需数量
        return temp;
    }

    /**
     * 通过MRP获取销售订单
     *
     * @param cond
     * @return
     */
    @Override
    public List<SaleOrderListDto> selectSaleOrderList(SaleOrderCond cond) {
        List<SaleOrderListDto> saleOrderListDtos = saleOrderService.selectSaleOrderListList(cond);
        int i = 0;
        for ( ;  i < saleOrderListDtos.size(); ) {
            //1.如果产品没有对应的结构清单则不在选择范围内
            if (StringUtils.isNull(bomMapper.selectBom(saleOrderListDtos.get(i).getProduceId()))){
                saleOrderListDtos.remove(i);
            }else {
                i++;
            }
        }
        return saleOrderListDtos;
    }

    /**
     * 销售产品通过MRP生成产品毛需求
     *
     * @param saleOrderList
     * @return
     */
    @Override
    public Bom selectDemandListBySaleOrderList(SaleOrderListDto saleOrderList) {
        if (StringUtils.isNull(bomService.selectBom(saleOrderList.getProduceId()))){
            return null;
        }
        Bom temp = bomService.selectBom(saleOrderList.getProduceId());
        Map<String, Double> map = warehouseService.selectProductNumber(new WarehouseCond());
        temp.setProduceNumber(map.get(temp.getProduceId()));
        temp.setNumberRequire(saleOrderList.getSaleOrderNumber());//成品数量
        temp.setProduceChild(selectDemandChildList(temp));//计算子件所需数量
        return temp;
    }

    /**
     * 计算子件所需数量
     * @param bom
     * @return
     */
    public List<Bom> selectDemandChildList(Bom bom){
        List<Bom> demandChild = bom.getProduceChild();
        Map<String, Double> map = warehouseService.selectProductNumber(new WarehouseCond());
        for (int i = 0; i < demandChild.size(); i++) {
            //计算数量
            demandChild.get(i).setNumberRequire(bom.getNumberRequire() * demandChild.get(i).getNumberRequire());
            demandChild.get(i).setProduceNumber(map.get(demandChild.get(i).getProduceId()));
            if (StringUtils.isNotNull(demandChild.get(i).getProduceChild())){
                //存在子件,递归
                demandChild.get(i).setProduceChild(selectDemandChildList(demandChild.get(i)));
            }
        }
        return demandChild;
    }

    /**
     * 毛需求通过MRP生成产品自产计划建议，产品采购建议
     *
     * @param bom
     * @return
     */
    @Override
    public List<MRP> getAdviseByDemandList(Bom bom) {
        List<MRP> temp = new ArrayList<>();
        List<Bom> boms = UtilsList.getBomList(bom);
        for (int i = 0; i < boms.size(); i++) {
            MRP mrp = new MRP(productMapper.selectProductById(boms.get(i).getProduceId()));
            if (StringUtils.isNotNull(bomMapper.selectBom(mrp.getProduceId()))){
                //存在
                mrp.setAdviseType("2");//采购：1，生产：2
            }else {
                //不存在
                mrp.setAdviseType("1");
            }
            mrp.setDemandNum(boms.get(i).getNumberRequire());
            mrp.setRemark(boms.get(i).getRemark());
            int j = 0;
            for (; j < temp.size(); j++) {
                if (temp.get(j).getProduceId().equals(mrp.getProduceId())){
                    //存在//累加
                    temp.get(j).setDemandNum(temp.get(j).getDemandNum() + mrp.getDemandNum());
                    break;
                }
            }
            if (j == temp.size()){
                //不存在，添加新的建议
                temp.add(mrp);
            }
        }
        return temp;
    }


    /**
     * 根据自产计划建议，生成生产计划
     * @param mrps
     * @return
     */
    @Override
    public int releaseProducePlanSelf(List<MRP> mrps) {
        System.out.println("生产计划生成");
        if (mrps.get(0).isType()){
            //若由销售计划生成，则仅生成销售物品对应的主生产计划
            try {
                return releaseProducePlanSelfBySale(mrps);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }else{
            //若由生产计划生成，则生成生产计划对应的子生产计划
            try {
                return releaseProducePlanSelfByUnfinished(mrps);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    }

    /**
     * 由销售计划生成，则仅生成销售物品对应的主生产计划
     * @param mrps
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int releaseProducePlanSelfBySale(List<MRP> mrps) throws Exception{
        String planSelfId = idUtil.createProducePlanSelfId();
        for (int i = 0; i < mrps.size(); i++) {
            if (StringUtils.isNotNull(saleOrderService.selectSaleOrderListById(mrps.get(i).getId(),mrps.get(i).getProduceId()))){
                //代表该建议对应产品在销售内，即仅生成主（父）生产计划
                ProducePlanSelfDomain producePlanSelf = new ProducePlanSelfDomain(mrps.get(i));
                producePlanSelf.setPlanSelfId(UtilsAdd.addOne(planSelfId,i));
                producePlanSelfService.insertProducePlanSelf(producePlanSelf);
            }//并不生成对应的子生产计划
        }
        return 1;
    }
    /**
     * 由生产计划生成，则生成生产计划对应的子生产计划
     * @param mrps
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int releaseProducePlanSelfByUnfinished (List<MRP> mrps) throws Exception{
        String planSelfId = idUtil.createProducePlanSelfId();
        for (int i = 1; i < mrps.size(); i++) {
            ProducePlanSelfDomain producePlanSelf = new ProducePlanSelfDomain(mrps.get(i));
            producePlanSelf.setPlanSelfId(UtilsAdd.addOne(planSelfId,i));
            producePlanSelfService.insertProducePlanSelf(producePlanSelf);
        }
        return 1;
    }

//    /**
//     * 检查该mrp的记录是否在计划表里已经重复
//     * @param mrp
//     * @return
//     */
//    public boolean checkPlanIfRepeated(MRP mrp) {
//
//    }


    /**
     *  根据采购建议，生成采购订单
     *
     * @param mrps
     * @return
     */
    @Override
    public int releasePurchaseApply(List<MRP> mrps) {
        //获取现有最新（大）采购申请单编号
        String purchaseApplyId = idUtil.createPurchaseApplyId();
        PurchaseApply purchaseApply = new PurchaseApply();
        //在现有最新（大）采购申请单编号基础上加一
        purchaseApply.setPurchaseApplyId(purchaseApplyId);
        //与对应销售/生产关联
        purchaseApply.setPlanSaleId(mrps.get(0).getId());
        if (mrps.get(0).isType()){
            purchaseApply.setRemark("MRP运算：由销售计划驱动");
        }else{
            purchaseApply.setRemark("MRP运算：由生产计划驱动");
        }
        //确定采购申请单对应产品信息
        List<PurchaseApplyList> purchaseApplyLists = new ArrayList<PurchaseApplyList>();
        for (int i = 0; i < mrps.size(); i++) {
            PurchaseApplyList purchaseApplyList = new PurchaseApplyList();
            purchaseApplyList.setProduceId(mrps.get(i).getProduceId());//产品编号
            purchaseApplyList.setPurchaseApplyId(purchaseApply.getPurchaseApplyId());//关联申请单单据
            purchaseApplyList.setPurchaseApplyNumber(mrps.get(i).getDemandNum());//产品所需数量
            purchaseApplyList.setProducePurchasePrice(mrps.get(i).getProducePurchasePrice()); //产品相关申请单价
            purchaseApplyLists.add(purchaseApplyList);
        }
        //存入采购申请单对应产品信息
        purchaseApply.setPurchaseApplyLists(purchaseApplyLists);
        try {
            //新增采购申请单
            purchaseApplyService.insertPurchaseApply(purchaseApply);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
        return 1;
    }

    /**
     * 更新毛需求表
     * @param bom
     * @return
     */
    @Override
    public int updateDemandList(Bom bom) {
        int result = 0;
        try {
            result = bomService.updateBom(bom);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


}
